package com.qth.valet.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qth.valet.common.annotation.Release;
import com.qth.valet.common.enums.PropertyEnum;
import com.qth.valet.common.utils.AmountUtil;
import com.qth.valet.common.utils.CommonUtil;
import com.qth.valet.common.utils.CustomJsonUtil;
import com.qth.valet.common.utils.StatusConstants;
import com.qth.valet.entity.po.*;
import com.qth.valet.entity.property.Commission;
import com.qth.valet.entity.resp.AlipayNotifyResponse;
import com.qth.valet.payment.MyAlipayConfig;
import com.qth.valet.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/notify")
@RequiredArgsConstructor
public class NotifyController {

    private final MyAlipayConfig myAlipayConfig;

    private final DriverRechargeService  driverRechargeService;

    private final DriversService driversService;

    private final DriverBalanceDetailService driverBalanceDetailService;

    private final NoticeDriverService noticeDriverService;

    private final PropertyService propertyService;

    @PostMapping("/alipay")
    @Transactional(rollbackFor = Exception.class)
    @Release
    public String alipay(HttpServletRequest request) {
        // 获取支付宝POST过来反馈信息，将异步通知中收到的待验证所有参数都存放到map中
        Map<String, String> params = getStringStringMap(request);
        try {
            // 验签
            boolean signVerified = AlipaySignature.rsaCheckV1(params, myAlipayConfig.getAlipayPublicKey(), myAlipayConfig.getCharset(), myAlipayConfig.getSignType());
            if (!signVerified) {
                // 验签不通过
                log.error("验签失败");
                return "fail";
            }
            // 验签通过
            log.info("验签通过");
            // 解析结果
            AlipayNotifyResponse resp = CustomJsonUtil.convertMapToObject(params, AlipayNotifyResponse.class);
            // 更新充值订单状态
            driverRechargeService.update(new LambdaUpdateWrapper<DriverRecharge>()
                    .eq(DriverRecharge::getId, resp.getOut_trade_no())
                    .set(DriverRecharge::getStatus, StatusConstants.DRIVER_PAY_STATUS_PAYED)
                    .set(DriverRecharge::getCallbackParams, JSON.toJSONString(resp))
                    .set(DriverRecharge::getCallbackTime, resp.getNotify_time()));
            // 查询充值订单
            DriverRecharge driverRecharge = driverRechargeService.getById(resp.getOut_trade_no());
            if (driverRecharge != null) {
                Integer driverId = driverRecharge.getDriverId();
                // 需要判断充值类型，开通会员时：1.账户余额不增加、2.通知类型不同
                if (driverRecharge.getType() == StatusConstants.DRIVER_RECHARGE_TYPE_COMMON) {
                    // if 普通充值
                    // 更新账户余额
                    Long amount = driverRecharge.getAmount();
                    driversService.updateDriverBalancePlus(driverId, amount);
                    // 添加一条余额明细
                    DriverBalanceDetail detail = this.buildOneDriverBalanceDetail(driverRecharge);
                    driverBalanceDetailService.save(detail);
                    // 创建一条通知
                    noticeDriverService.save(new NoticeDriver()
                            .setDriverId(driverId)
                            .setType(StatusConstants.NOTICE_RECHARGE_SUCCESS)
                            .setContent("充值" + AmountUtil.formatAmount(amount) + "元成功")
                    );
                } else {
                    // else 开通会员
                    // 查询司机信息（需要知道他的会员过期时间，做续期）
                    Driver driver = driversService.getById(driverId);
                    // 会员类型
                    int vipType;
                    Date vipExpireTime;
                    if (driverRecharge.getType() == StatusConstants.DRIVER_RECHARGE_TYPE_MONTH_VIP) {
                        vipType = StatusConstants.DRIVER_VIP_MONTH;
                        vipExpireTime = CommonUtil.getDateAfterOneMonth(driver.getVipExpireTime());
                    } else {
                        vipType = StatusConstants.DRIVER_VIP_YEAR;
                        vipExpireTime = CommonUtil.getDateAfterOneYear(driver.getVipExpireTime());
                    }
                    // 更新司机为会员、更新过期时间；发通知
                    LambdaUpdateWrapper<Driver> uw = new LambdaUpdateWrapper<>();
                    uw.eq(Driver::getId, driverId)
                            .set(Driver::getVipType, vipType)
                            .set(Driver::getVipExpireTime, vipExpireTime)
                    ;
                    driversService.update(uw);
                    // 创建一条通知
                    noticeDriverService.save(new NoticeDriver()
                            .setDriverId(driverId)
                            .setType(StatusConstants.NOTICE_VIP)
                            .setContent("您已成功开通" + ((vipType == StatusConstants.DRIVER_VIP_MONTH) ? "月度" : "年度")
                            + "会员。在会员有效期间，平台将不再抽取提成！")
                    );

                    // 上线司机提成 增加余额 + 插入明细 + 通知
                    if (driver.getPid() != null && driver.getPid() != 0) {
                        Integer pid = driver.getPid();
                        // 查询上线司机信息
                        Driver father = driversService.getById(pid);
                        // 司机不在线 不给提成
                        if (father != null && CommonUtil.isDriverOnline(father.getStatus())) {
                            // 上线加充值提成
                            String commissionKey = PropertyEnum.COMMISSION.getKey();
                            Property commissionObject = propertyService.getById(commissionKey);
                            Commission commission = (Commission) PropertyEnum.COMMISSION.parse(commissionObject.getTheValue());
                            // 提成金额
                            Long fatherAmount = (long) Math.ceil((commission.getFather() * driverRecharge.getAmount()));

                            // 更新司机余额
                            driversService.updateDriverBalancePlus(pid, fatherAmount);
                            // 插入明细
                            DriverBalanceDetail dbt = new DriverBalanceDetail();
                            dbt.setDriverId(pid);                               // 上线司机ID
                            dbt.setChildId(driver.getId());                     // 当前司机ID
                            dbt.setRechargeId(driverRecharge.getId());          // 孩子的充值订单ID
                            dbt.setBalanceType(StatusConstants.BALANCE_TYPE_CHILD_OPEN_VIP); // 孩子开通VIP的上线提成
                            dbt.setAmount(fatherAmount);
                            // 余额已修改，直接查
                            dbt.setRemainingBalance(driversService.getById(pid).getAccountBalance());
                            log.info("更新上线司机账户余额，司机ID：{}，增加{}", pid, fatherAmount);

                            // 插入一条司机余额明细
                            driverBalanceDetailService.save(dbt);

                            // 通知
                            noticeDriverService.save(new NoticeDriver()
                                    .setDriverId(father.getId())
                                    .setType(StatusConstants.NOTICE_COMMISSION_INCOME)
                                    .setContent(
                                            "您的下线“" +
                                            driver.getSurname() + driver.getName() +
                                            "”开通了" + (driverRecharge.getType() == StatusConstants.DRIVER_RECHARGE_TYPE_MONTH_VIP ? "月度" : "年度") +
                                            "会员。为您带来" + AmountUtil.formatAmount(fatherAmount) + "元的收益"
                                    )
                            );
                            // 将司机的通知读取状态改为未读
                            driversService.updateNoticeReadStatus(father.getId(), false);
                        }

                    }
                }
                // 将司机的通知读取状态改为未读
                driversService.updateNoticeReadStatus(driverId, false);
            }
            // 返回success给支付宝
            return "success";
        } catch (AlipayApiException e) {
            log.error("验签异常");
            return "fail";
        }
    }

    private DriverBalanceDetail buildOneDriverBalanceDetail(DriverRecharge driverRecharge) {
        DriverBalanceDetail driverBalanceDetail = new DriverBalanceDetail();
        driverBalanceDetail.setDriverId(driverRecharge.getDriverId());
        driverBalanceDetail.setRechargeId(driverRecharge.getId());
        driverBalanceDetail.setBalanceType(StatusConstants.BALANCE_TYPE_RECHARGE_INCOME);
        driverBalanceDetail.setAmount(driverRecharge.getAmount());
        Driver driver = driversService.getById(driverRecharge.getDriverId());
        // 余额已修改，直接查
        driverBalanceDetail.setRemainingBalance(driver.getAccountBalance());
        return driverBalanceDetail;
    }

    private Map<String, String> getStringStringMap(HttpServletRequest request) {
        Map<String , String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        return params;
    }

}
